import tensorflow.compat.v1 as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

ALPHA = 1e-2
ITERS = 2000

tf.random.set_random_seed(777)
np.random.seed(777)

path = '../data-03-diabetes.csv'
data = np.loadtxt(path, delimiter=',')

x_data = data[:, :-1]
y_data = data[:, -1:]

scaler = StandardScaler()
x_data = scaler.fit_transform(x_data)
M, N = x_data.shape

x_data_train, x_data_test, y_data_train, y_data_test = train_test_split(x_data, y_data, train_size=0.8, random_state=777)

x = tf.placeholder(tf.float32, [None, N], name='ph_x')
y = tf.placeholder(tf.float32, [None, 1], name='ph_y')

w = tf.Variable(tf.random.normal([N, 1]), dtype=tf.float32, name='w')
b = tf.Variable(tf.random.normal([1, 1]), dtype=tf.float32, name='b')

z = tf.add(tf.matmul(x, w), b, name='z')

a = tf.sigmoid(z, name='a')

j = tf.divide(
    tf.matmul(
        tf.transpose(y),
        tf.log(a)
    )
    +
    tf.matmul(
        tf.transpose(1 - y),
        tf.log(1 - a)
    ),
    - tf.cast(tf.shape(x)[0], tf.float32),
    name='j'
)

dz = tf.subtract(a, y, name='dz')
dw = tf.divide(
    tf.matmul(
        tf.transpose(x),
        dz
    ),
    tf.cast(tf.shape(x)[0], tf.float32),
    name='dw'
)
db = tf.reduce_mean(a - y, name='db')

update = [
    tf.assign(w, w - ALPHA * dw),
    tf.assign(b, b - ALPHA * db),
]

acc = tf.reduce_mean(tf.cast(tf.equal(a > 0.5, y > 0.5), tf.float32), name='acc')

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    cost_his = np.zeros(ITERS)
    GROUP = int(np.ceil(ITERS / 20))
    for i in range(ITERS):
        _, cost_v, acc_v = sess.run([update, j, acc], feed_dict={x: x_data_train, y: y_data_train})
        cost_v = cost_v[0][0]
        cost_his[i] = cost_v
        if i % GROUP == 0:
            print(f'#{i + 1}: cost = {cost_v}, acc = {acc_v}')
    if i % GROUP != 0:
        print(f'#{i + 1}: cost = {cost_v}, acc = {acc_v}')

    plt.plot(cost_his)
    plt.show()

    acc_v = sess.run(acc, feed_dict={x: x_data_test, y: y_data_test})
    print(f'Test acc = {acc_v}')
